﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using smartcrm.Models;
using System.Configuration;
using System.ComponentModel;
using System.IO;
using smartcrm.Utilities;

namespace smartcrm.Controllers
{
    public class BaseController : Controller
    {
        public static string AUTO_NUMBER = ConfigurationManager.AppSettings["AutoNumber"].ToString();
        public static string LOGIN_USER = ConfigurationManager.AppSettings["AuthSaveKey"].ToString();
        public static string PORTAL_LOGIN_USER = ConfigurationManager.AppSettings["PortalAuthSaveKey"].ToString();
        public static string APPLICATION_NAME = ConfigurationManager.AppSettings["ApplicationName"].ToString();
        public static string APPLICATION_VERSION = ConfigurationManager.AppSettings["ApplicationVersion"].ToString();
        public static string APPLICATION_RELEASE_DATE = ConfigurationManager.AppSettings["ApplicationReleaseDate"].ToString();
        public static string TEMPLATE_PATH = ConfigurationManager.AppSettings["TemplatePath"].ToString();
        public static string FILE_GENERATION_PATH = ConfigurationManager.AppSettings["FileGenerationPath"].ToString();
        public static string LOGO_PATH = ConfigurationManager.AppSettings["LogoPath"].ToString();
        public static string ORDER_QUERY_URL = ConfigurationManager.AppSettings["HostURL"].ToString() + "/Query/Order/";
        public static string BUG_ATTACHMENT_PATH = ConfigurationManager.AppSettings["BugAttachmentPath"].ToString();
        public static bool IS_DEMO = bool.Parse(ConfigurationManager.AppSettings["IsDemo"].ToString());

        public static string ORDER_STATUS_CREATED = "101";
        public static string ORDER_STATIS_COMPLETE = "999";

        public static string MSG_NoEntityFound = "保存失败：没有找到实体";
        public static string MSG_SystemReserved= "保存失败：无法更改系统保留数据";
        public static string MSG_IsDemo = "保存失败：此系统仅作为演示，无法更改";

        public static PagerConfig GetPagerConfig(string currentPage)
        {
            PagerConfig config = new PagerConfig();
            int page = 1;
            try
            {
                page = int.Parse(currentPage);
            }
            catch
            {
                page = 1;
            }            
            config.CurrentPage = page;
            return config;
        }


        private SmartCrmEntities _context;
        public SmartCrmEntities Context
        {
            get
            {
                if (_context == null)
                {
                    _context = new SmartCrmEntities();
                }
                return _context;
            }
        }      

        /// <summary>
        /// CompanyNo can come from SmartCRM or Portal
        /// </summary>
        public string CompanyNo
        {
            get
            {
                if (Session[LOGIN_USER] != null)
                {
                    return GetLoginUser().CompanyNo;
                }
                else if (Session[PORTAL_LOGIN_USER] != null)
                {
                    return GetPortLoginUser().CompanyNo;
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        public AttachmentConfig AttachmentConfigurate
        {
            get
            {
                AttachmentConfig config = new AttachmentConfig();
                Company c = Context.Company.First(m => m.CompanyNo == CompanyNo);
                config.SizeLimitation = (float)c.AttachmentSize;
                config.RootPath = c.AttachmentRoot;
                return config;
            }
        }

        public BaseController()
        {
        }

        public string OrderTemplate
        {
            get
            {
                SmartCrmEntities context = new SmartCrmEntities();
                Company c = Context.Company.FirstOrDefault(m => m.CompanyNo == CompanyNo);
                if (c == null)
                {
                    return string.Empty;
                }
                else
                {
                    return c.OrderTemplate;
                }
            }
        }

        protected String GetNewIdNumber(IdNumberType typeEnum)
        {
            string type = ((int)typeEnum).ToString();
            SmartCrmEntities context = new SmartCrmEntities();
            int no = 0;
            PoolRestore restore = context.PoolRestore.FirstOrDefault(m => m.CompanyNo == CompanyNo && m.NoType == type);
            if (restore != null)
            {
                context.PoolRestore.DeleteObject(restore);
                context.SaveChanges();
                no = restore.No;
            }
            else
            {

                NoPool pool = context.NoPool.FirstOrDefault(m => m.CompanyNo == CompanyNo && m.NoType == type);
                if (pool == null)
                {
                    pool = new NoPool();
                    pool.CompanyNo = CompanyNo;
                    pool.Base = InitialPoolBase(typeEnum);
                    pool.NoType = type;
                    no = pool.Base;
                    pool.Base += 1;
                    context.NoPool.AddObject(pool);
                    context.SaveChanges();
                }
                else
                {
                    no = pool.Base;
                    pool.Base += 1;

                    // 999999 is reserved for OrderStatus, so ignore and use next number
                    if (typeEnum == IdNumberType.OrderStatus && no == 999)
                    {
                        pool.Base += 1;
                        no++;
                    }
                    context.SaveChanges();
                }
            }

            return CompanyNo + no.ToString();
        }

        public string CombineIds(List<string> ids)
        {
            string result = string.Empty;
            foreach (string i in ids)
            {
                result = result + i + ",";
            }
            if (result.Length > 1)
            {
                return result.Substring(0, result.Length - 1);
            }
            else
            {
                return string.Empty;
            }
        }

        public void PutbackNos(List<IdNumber> nos)
        {
            foreach (IdNumber no in nos)
            {
                PutbackNo(no.No, no.Type);
            }
        }

        public void PutbackNo(string NoWithCompanyNo, IdNumberType typeEnum)
        {
            if (string.IsNullOrEmpty(NoWithCompanyNo))
            {
                return;
            }

            SmartCrmEntities context = new SmartCrmEntities();
            int no = int.Parse(NoWithCompanyNo.Substring(CompanyNo.Length));
            string type = ((int)typeEnum).ToString();

            PoolRestore restore = context.PoolRestore.FirstOrDefault(m => m.CompanyNo == CompanyNo && m.NoType == type && m.No == no);
            if (restore == null)
            {
                PoolRestore res = new PoolRestore();
                res.CompanyNo = CompanyNo;
                res.NoType = type;
                res.No = no;
                context.PoolRestore.AddObject(res);
                
                context.SaveChanges();               
            }
        }

        public int InitialPoolBase(IdNumberType type)
        {
            switch (type)
            {
                case IdNumberType.Order:
                    return 100001;
                case IdNumberType.Customer:
                    return 102;
                case IdNumberType.Factory:
                    return 1001;
                case IdNumberType.WorkFlow:
                    return 101;
                case IdNumberType.WorkFlowStep:
                    return 1001;
                case IdNumberType.Department:
                    return 101;
                case IdNumberType.OrderStatus:
                    return 102;  //101, 1002 and 999 are used during creating company
                case IdNumberType.ContributionRatio:
                    return 101;
                case IdNumberType.PaymentType:
                    return 102;  //101 are used during creating company
                case IdNumberType.Contact:
                    return 1001;
                case IdNumberType.OrderFlow:
                    return 1000001;
                case IdNumberType.User:
                    return 11; //10 is used during creating company
                case IdNumberType.OrderAttachment:
                    return 1000001;
                case IdNumberType.OrderMemo:
                    return 1000001;
                case IdNumberType.Bug:
                    return 1000001;
                case IdNumberType.BugAttachment:
                    return 1001;
                default:
                    return 1001;
            }
        }

        public LoginUser GetLoginUser()
        {
            return Session[LOGIN_USER] as LoginUser;
        }

        public PortalUser GetPortLoginUser()
        {
            return Session[PORTAL_LOGIN_USER] as PortalUser;
        }

        public List<SimpleItemList> GetOrderPaymentStatusDdl()
        {
            return EnumHelper.GetDdlListWithIntId(typeof(OrderPaymentStatus), true);
        }

        public List<SimpleItemList> GetOrderStatusDdl()
        {
            List<SimpleItemList> status = Context.OrderStatus.Where(m => m.CompanyNo == CompanyNo).Select(m => new SimpleItemList() { ItemText = m.StatusName, ItemValue = m.StatusNo }).ToList();
            status.Insert(0, new SimpleItemList() { ItemValue = string.Empty, ItemText = string.Empty });
            return status;
        }

        public List<SimpleItemList> BindWorkFlowDdl()
        {
            List<SimpleItemList> facotries = Context.WorkFlow.Where(m => m.CompanyNo == CompanyNo).Select(m => new SimpleItemList() { ItemText = m.WorkFlowName, ItemValue = m.WorkFlowNo }).ToList();
            facotries.Insert(0, new SimpleItemList() { ItemValue = string.Empty, ItemText = string.Empty });
            return facotries;
        }


        public List<SimpleItemList> BindFactoryDdl()
        {
            List<SimpleItemList> facotries = Context.Factory.Where(m => m.IsActive == true && m.CompanyNo == CompanyNo).Select(m => new SimpleItemList() { ItemText = m.FactoryName, ItemValue = m.FactoryNo }).ToList();
            facotries.Insert(0, new SimpleItemList() { ItemValue = string.Empty, ItemText = string.Empty });
            return facotries;
        }

        public List<SimpleItemList> BindCustomerDdl()
        {
            List<SimpleItemList> customers = Context.Customer.Where(m => m.IsActive == true && m.CompanyNo == CompanyNo).Select(m => new SimpleItemList() { ItemText = m.CustomerShortName, ItemValue = m.CustomerNo }).ToList();
            customers.Insert(0, new SimpleItemList() { ItemValue = string.Empty, ItemText = string.Empty });
            return customers;
        }

        public List<SimpleItemList> BindOrderStatusDdl()
        {
            List<SimpleItemList> status = Context.OrderStatus.Where(m => m.CompanyNo == CompanyNo).Select(m => new SimpleItemList() { ItemText = m.StatusName, ItemValue = m.StatusNo }).ToList();
            status.Insert(0, new SimpleItemList() { ItemValue = string.Empty, ItemText = string.Empty });
            return status;
        }

        private List<SimpleItemList> _paymentTypeDdl;
        public List<SimpleItemList> PaymentTypeDdl
        {
            get
            {
                if (_paymentTypeDdl == null)
                {
                    SmartCrmEntities context = new SmartCrmEntities();
                    List<PaymentType> payments = Context.PaymentType.Where(m=>m.CompanyNo == CompanyNo).ToList();
                    _paymentTypeDdl = new List<SimpleItemList>();
                    foreach (PaymentType p in payments)
                    {
                        _paymentTypeDdl.Add(new SimpleItemList() { ItemValue = p.TypeName, ItemText = p.TypeName });
                    }
                    return _paymentTypeDdl;
                }
                else
                {
                    return _paymentTypeDdl;
                }
            }
        }

        public string GetOrderPaymentStatusString(string id)
        {
            return EnumHelper.GetEnumDescriptionByValue(typeof(OrderPaymentStatus), id);
        }

        public string GetOrderQueryNo()
        {
            Random r = new Random();
            return r.Next(1000, 9999).ToString();
        }

        public void SetOrderPaymentStatus(Order order)
        {
            if (!order.Paid.HasValue || order.Paid.Value == 0)
            {
                order.PaymentStatus = ((int)OrderPaymentStatus.Unpaid).ToString();
            }
            else if (order.Paid.HasValue && order.Paid == order.Amount)
            {
                order.PaymentStatus = ((int)OrderPaymentStatus.Paid).ToString();
            }
            else if (order.Paid.HasValue && order.Paid < order.Amount)
            {
                order.PaymentStatus = ((int)OrderPaymentStatus.PartPaid).ToString();
            }
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        protected void AddErrorMessage(string message)
        {
            string FilePath = Path.Combine(Server.MapPath("/"), "log");
            DateTime dt = DateTime.Now;
            String FileName = Path.Combine(FilePath, dt.ToString("yyyyMMdd") + ".txt");
            Exception ex = Server.GetLastError();
            try
            {
                System.IO.File.AppendAllText(FileName, string.Format("{0} {1}", "ERROR " + dt.ToString("HH:mm:ss"), message + System.Environment.NewLine + System.Environment.NewLine));
            }
            catch
            {
            }
        }

        public string GetUrl(JsUrl model)
        {
            string url = model.root;
            
            for (int i = 0; i < model.paras.Count; i++)
            {
                if (i == 0)
                {
                    url += "?" + model.paras[i].name + "=" + model.paras[i].value;
                }
                else
                {
                    url += "&" + model.paras[i].name + "=" + model.paras[i].value;
                }
            }
            return url;
        }
    }
}